package com.halflife.framework.generator.template.mapper;

import com.halflife.framework.generator.GenerateUtil;
import com.halflife.framework.generator.annotation.QueryAnn;
import org.apache.commons.lang.StringUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by zhaoyf on 2018/6/18.
 */
public abstract class BaseAnalysis {
    protected StringBuilder xmlStr;
    protected Class clazz;
    protected String tableName;
    protected List<Field> fields;
    protected Map<String, Field> fieldMap;
    protected boolean isTwoAnalysis = false;

    public StringBuilder getJoinStrs() {
        return joinStrs;
    }
    public StringBuilder getFieldStrs() {
        return fieldStrs;
    }

    public void setJoinStrs(String joinStrs) {
        if (this.joinStrs == null) {
            this.joinStrs = new StringBuilder();
        }
        this.joinStrs.append(joinStrs);
    }
    public void setFieldStrs(String fieldStrs) {
        if (this.fieldStrs == null) {
            this.fieldStrs = new StringBuilder();
        }
        this.fieldStrs.append(fieldStrs);
    }

    protected StringBuilder joinStrs;
    protected StringBuilder fieldStrs;
    protected String[] prefixs = {"t","a","b","c","d","e","f","g"};
    protected int objs = 0;

    protected String getOperate(String propName) {
        QueryAnn type = fieldMap.get(propName).getAnnotation(QueryAnn.class);
        if (type != null && StringUtils.isNotBlank(type.operate())) {
            return type.operate();
        }
        return "=";
    }
    protected void setBindStr() {
        for (Field field : fields) {
            String key = field.getName();
            QueryAnn type = fieldMap.get(key).getAnnotation(QueryAnn.class);
            if (type != null && "like".equals(type.operate())) {
                xmlStr.append("<if test=\"_parameter.containsKey('" + key + "') and " + key + " != null\">\n");
                xmlStr.append("\t<bind name=\"");
                xmlStr.append(key);
                xmlStr.append("\" value=\"'%' + _parameter."+key+" + '%'\" />\n");
                xmlStr.append("\t</if>\n");
            }
        }
    }

    protected BaseAnalysis(Class clazz) {
        fieldMap = new HashMap<>();
        fields = new ArrayList<>();
        this.clazz = clazz;
        QueryAnn type = (QueryAnn) clazz.getAnnotation(QueryAnn.class);
        this.tableName = (type!=null&&StringUtils.isNotBlank(type.table()))?type.table():"t_" + clazz.getSimpleName().toLowerCase();
        xmlStr = new StringBuilder();
        GenerateUtil.setFieldsBySequence(clazz,fieldMap,fields);
    }

    public String analysis() {
        this.setPrefix();

        this.fieldAnaysis1();
        if (isTwoAnalysis) {
            this.middleAnaysis();
            this.fieldAnaysis2();
        }

        this.setSuffix();
        return xmlStr.toString();
    }

    protected void comma() {
        if(!isComma){
            xmlStr.append(",");
        }else{
            isComma = false;
        }
    }
    protected boolean isComma = true;

    protected void fieldAnaysis1() {
        final int[] len = {0};
        isComma = true;
        for (Field field : fields) {
            if(field.getType()== List.class){
                continue;
            }
            CustomField customField = new CustomField(field);
            String str = this.getValue1(customField);
            if (StringUtils.isNotBlank(str)) {
                this.comma();
                xmlStr.append("\t");
                xmlStr.append(str);
                len[0] += str.length();
                xmlStr.append(this.getLineSuffix(len));
            }

        }
    }


    protected void fieldAnaysis2() {
        final int[] len = {0};
        isComma = true;
        for (Field field : fields) {
            if(field.getType()== List.class){
                continue;
            }
            CustomField customField = new CustomField(field);
            String str = this.getValue2(customField);
            if (StringUtils.isNotBlank(str)){
                this.comma();
                xmlStr.append("\t");
                xmlStr.append(str);
                len[0] += str.length();
                xmlStr.append(this.getLineSuffix(len));
            }

        }
    }

    protected void middleAnaysis() {

    }

    protected String getQueryString(CustomField customField) {
        if ( !customField.isQueryed() && !customField.isPersist()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("<if test=\"_parameter.containsKey('" + customField.getName() + "') and " + customField.getName() + " != null\">\n");
        if (StringUtils.isNotBlank(customField.getCustomName())) {
            sb.append("\t\t and ").append(customField.getCustomName()).append(" ").append(customField.getOperate());
        }else{
            sb.append("\t\t and ").append(this.prefixs[this.objs]).append(".").append(customField.getRealName()).append(" ").append(customField.getOperate());
        }

        sb.append(" #{").append(customField.getName()).append(",jdbcType=").append(customField.getTypeName()).append("}\n");
        sb.append("\t</if>\n");
        return sb.toString();
    }

    protected void setEndQueryString() {
        xmlStr.append("\t<if test=\"_parameter.containsKey('endSql') and endSql != null\">\n");
        xmlStr.append("\t\t and ${endSql} \n");
        xmlStr.append("\t</if>\n");
    }
    protected void setOrderQueryString() {
        xmlStr.append("\t<choose>\n");
        xmlStr.append("\t\t<when test=\"_parameter.containsKey('orderSql') and orderSql != null\">\n");
        xmlStr.append("\t\t  order by ${orderSql} \n");
        xmlStr.append("\t\t</when>\n");
        xmlStr.append("\t\t<otherwise>\n");
        xmlStr.append("\t\t  order by  ").append(this.prefixs[0]).append(".id desc \n");
        xmlStr.append("\t\t</otherwise>\n");
        xmlStr.append("\t</choose>\n");
    }

    protected abstract void setPrefix();

    protected String getValue1(CustomField field) {
        return "";
    }

    ;

    protected String getValue2(CustomField field) {
        return "";
    }

    ;

    protected String getLineSuffix(int[] len) {
        if (len[0] > 100) {
            len[0] = 0;
            return "\n";
        }
        return "";
    }

    ;

    protected void setSuffix() {

    }

    ;
}
